/*******************************************************************************
 * Copyright (c) 2000, 2010 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package com.nauu.atombuilder.editors;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.EventObject;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.LightweightSystem;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.Viewport;
import org.eclipse.draw2d.parts.ScrollableThumbnail;
import org.eclipse.draw2d.parts.Thumbnail;
import org.eclipse.gef.ContextMenuProvider;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gef.MouseWheelHandler;
import org.eclipse.gef.MouseWheelZoomHandler;
import org.eclipse.gef.RootEditPart;
import org.eclipse.gef.SnapToGrid;
import org.eclipse.gef.dnd.TemplateTransferDropTargetListener;
import org.eclipse.gef.editparts.ScalableFreeformRootEditPart;
import org.eclipse.gef.editparts.ZoomManager;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.gef.ui.parts.ContentOutlinePage;
import org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette;
import org.eclipse.gef.ui.parts.TreeViewer;
import org.eclipse.gef.ui.properties.UndoablePropertySheetEntry;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.TransferDropTargetListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.part.IPageSite;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.PropertySheetPage;

import com.nauu.atombuilder.AtomBuilderPlugin;
import com.nauu.atombuilder.actions.TemplateAction;
import com.nauu.atombuilder.dnd.DiagramTemplateTransferDropTargetListener;
import com.nauu.atombuilder.modle.Diagram;
import com.nauu.atombuilder.parts.PartFactory;
import com.nauu.atombuilder.parts.TreePartFactory;
import com.nauu.atombuilder.policies.CustomPropertySheetPage;
import com.nauu.atombuilder.util.PaletteFactory;

public class AtomEditor extends GraphicalEditorWithFlyoutPalette {

	private Diagram diagram = new Diagram();
	
	private PropertySheetPage propertySheetPage;
	
	public Diagram getDiagram() {
		return diagram;
	}

	public void setDiagram(Diagram diagram) {
		this.diagram = diagram;
	}

	public AtomEditor() {
		super();
		this.setEditDomain(new DefaultEditDomain(this));
	}
	
	@Override
	public void commandStackChanged(EventObject event) {
		super.commandStackChanged(event);
		firePropertyChange(IEditorPart.PROP_DIRTY);
	}
	
	protected void configureGraphicalViewer() {
		super.configureGraphicalViewer();
		ScalableFreeformRootEditPart root = new ScalableFreeformRootEditPart();
		getGraphicalViewer().setRootEditPart(root);
		getGraphicalViewer().setEditPartFactory(new PartFactory());
		
		getGraphicalViewer().setProperty(SnapToGrid.PROPERTY_GRID_ENABLED,  new Boolean(true));  
        getGraphicalViewer().setProperty(SnapToGrid.PROPERTY_GRID_VISIBLE, true);  
		
	}

	@Override
	protected PaletteRoot getPaletteRoot() {
		PaletteRoot paletteRoot = PaletteFactory.createPalette();
		return paletteRoot;
	}
	
	protected void initializeGraphicalViewer() { 
		getGraphicalViewer().setContents(getDiagram());
		getGraphicalViewer().addDropTargetListener(new DiagramTemplateTransferDropTargetListener(getGraphicalViewer()));
		getGraphicalViewer().setProperty(MouseWheelHandler.KeyGenerator.getKey(SWT.CTRL), MouseWheelZoomHandler.SINGLETON);  
	} 

	protected void writeToOutputStream(OutputStream os) throws IOException {
		ObjectOutputStream out = new ObjectOutputStream(os);
		out.writeObject(getDiagram());
		out.close();
	}
	
	protected void saveProperties() {
	}
	
	@Override
	public void doSave(final IProgressMonitor progressMonitor) {
		try {
//			System.out.println("doSave");
			IFile file = ((IFileEditorInput) getEditorInput()).getFile();
			ByteArrayOutputStream out = new ByteArrayOutputStream();
//			writeToOutputStream(out);
			ObjectOutputStream os = new ObjectOutputStream(out);
			os.writeObject(getDiagram());
			file.setContents(new ByteArrayInputStream(out.toByteArray()), true,
					false, progressMonitor);
			os.close();
			out.close();

			getCommandStack().markSaveLocation();
			
//			export(getGraphicalViewer(), filePath+"/atom.jpeg", SWT.IMAGE_JPEG);
//			xmlSave(progressMonitor);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
	
    public boolean isDirty() {
        return getCommandStack().isDirty();
    }
	
    public boolean isSaveAsAllowed() {
        return true;
    }
    
//	protected void superSetInput(IEditorInput input) {
//		// The workspace never changes for an editor. So, removing and re-adding
//		// the
//		// resourceListener is not necessary. But it is being done here for the
//		// sake
//		// of proper implementation. Plus, the resourceListener needs to be
//		// added
//		// to the workspace the first time around.
//		if (getEditorInput() != null) {
//			IFile file = ((IFileEditorInput) getEditorInput()).getFile();
//			file.getWorkspace().removeResourceChangeListener(resourceListener);
//		}
//
//		super.setInput(input);
//
//		if (getEditorInput() != null) {
//			IFile file = ((IFileEditorInput) getEditorInput()).getFile();
//			file.getWorkspace().addResourceChangeListener(resourceListener);
//			setPartName(file.getName());
//		}
//	}
    
    protected void setInput(IEditorInput input) {
        super.setInput(input);

                IFile file = ((IFileEditorInput) input).getFile();
//        diagram = new Diagram();
                try { // attempt to read from a file
                    InputStream istream = file.getContents(false);
//                    XStream xs = new XStream();
//                    this.diagram = (Diagram)xs.fromXML(istream,new Diagram());
                    diagram = Diagram.makeFromStream(istream);
                    istream.close();
                } catch (Exception e) { // but if there's an error, create a new diagram
                    e.printStackTrace();
                    diagram = new Diagram();
                }
    }
    
    
    

//    public void export(GraphicalViewer viewer, String location, int format) 
//
//        { 
//
//            try 
//
//            { 
//
//               IFigure figure = ((AbstractGraphicalEditPart) viewer.getRootEditPart()).getFigure(); 
//
//           
//
//           
//
//               File file = new File(location); 
//
//               if (file.exists()) 
//
//               { 
//
//                   if (!MessageDialog.openQuestion(null, "系统提示", 
//
//                   "该文件已经存在. 要重新覆盖它吗 ?")) 
//
//                   { 
//
//                       return; 
//
//                   }
//
//               } 
//
//               else 
//
//               { 
//
//               file.createNewFile(); 
//
//               } 
//
//           
//
//           
//
//               FileOutputStream fos = new FileOutputStream(file); 
//
//           
//
//           
//
//               if (figure instanceof Viewport) 
//
//               { 
//
//               // Reinit the figure 
//
//               ((Viewport) figure).setViewLocation(0, 0); 
//
//               } 
//
//           
//
//           
//
//               Dimension size = figure.getPreferredSize(); 
//
//               Image image = new Image(Display.getDefault(), size.width, size.height); 
//
//               GC gc = new GC(image); 
//
//               SWTGraphics graphics = new SWTGraphics(gc); 
//
//               figure.paint(graphics); 
//
//           
//
//           
//
//               ImageLoader loader = new ImageLoader(); 
//
//               loader.data = new ImageData[] {image.getImageData()}; 
//
//               loader.save(fos, format); 
//
//               fos.close();
//
//               
//
//            } 
//
//            catch (Exception e) 
//
//            { 
//
//           //记录该异常
//
////             ModelerPlugin.displayDialog(null, "An error occured during export. See the error log for more details.", IStatus.ERROR); 
//
////             ModelerPlugin.log(e); 
//
//            }finally{
//
//                
//
//            }
//
//        }
//
//     
//    public void xmlSave(IProgressMonitor progressMonitor) {
//    	try {
//    		InputStream is = AtomBuilderPlugin.class.getResourceAsStream("/tlp/grid.ftl");
//			IFile file = ((IFileEditorInput) getEditorInput()).getFile();
//			File currentFile = file.getLocation().toFile();
//			String fileName = currentFile.getName();
//			String filePath = currentFile.getPath();
//			FileOutputStream fs = new FileOutputStream(filePath);
//			XStream xs = new XStream();
//			xs.toXML(getDiagram(), fs);
//		} catch (FileNotFoundException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//
//        Platform.run(new SafeRunnable() {
//
//        public void run() throws Exception {
//
//          
//
//        //以下存储xml文件
//
//          
//
//        Document document = DocumentHelper.createDocument();
//
//        
//
//        Element logicDiagramElement = document.addElement("LogicDiagram");
//
//        /*中间是你的xml*/
//
//        try{
//
//        	List<Node> list = getDiagram().getNodes();
//        	for (Node node : list) {
//        		System.out.println("=====================");
//				System.out.println(node.getName()+":");
//				System.out.println(node.getLocation().x+":"+node.getLocation().y);
//				System.out.println("=====================");
//			}
//        	
//        	
//        OutputFormat format = OutputFormat.createPrettyPrint();
//
////      IFile file = ((IFileEditorInput)getEditorInput()).getFile();
//
////      final IFile file = (IFile) ((DiagramEditorInput)getEditorInput()).getFile();
//
//        IFile file =((IFileEditorInput)getEditorInput()).getFile(); 
//
//        File f = file.getLocation().toFile();
//
//        System.out.println("fileName:"+f.getName()); 
//
//        XMLWriter output = new XMLWriter(new FileOutputStream( f ),format);
//
//        
//
//        output.write(document);   
//
//        output.close();
//
//        } catch(IOException e){
//
//        System.out.println(e.getMessage());
//
//        }
//
//        getCommandStack().markSaveLocation();
//
//        }
//
//        });


//}


	protected void createActions() {
		super.createActions();
		ActionRegistry registry = getActionRegistry();
		IAction action;
	
		
		action = new TemplateAction(this);
		registry.registerAction(action);
		getSelectionActions().add(action.getId());
	}

	@Override
	public Object getAdapter(Class type) {
		if (type == IPropertySheetPage.class){
			propertySheetPage = new CustomPropertySheetPage();
			propertySheetPage.setRootEntry(new UndoablePropertySheetEntry(this.getCommandStack()));
			return propertySheetPage;
		}
        if (type == IContentOutlinePage.class){
        	return new OutlinePage(new TreeViewer());
        }
		return super.getAdapter(type);
	}
	
	protected FigureCanvas getEditor() {
		return (FigureCanvas) getGraphicalViewer().getControl();
	}
	
	class OutlinePage extends ContentOutlinePage implements IAdaptable {

		private PageBook pageBook;
		private Control outline;
		private Canvas overview;
		private IAction showOutlineAction, showOverviewAction;
		static final int ID_OUTLINE = 0;
		static final int ID_OVERVIEW = 1;
		private Thumbnail thumbnail;
		private DisposeListener disposeListener;

		public OutlinePage(EditPartViewer viewer) {
			super(viewer);
		}

		public void init(IPageSite pageSite) {
			super.init(pageSite);
			ActionRegistry registry = getActionRegistry();
			IActionBars bars = pageSite.getActionBars();
			String id = ActionFactory.UNDO.getId();
			bars.setGlobalActionHandler(id, registry.getAction(id));
			id = ActionFactory.REDO.getId();
			bars.setGlobalActionHandler(id, registry.getAction(id));
			id = ActionFactory.DELETE.getId();
			bars.updateActionBars();
		}

		protected void configureOutlineViewer() {
			getViewer().setEditDomain(getEditDomain());
			getViewer().setEditPartFactory(new TreePartFactory());
			getViewer().addDropTargetListener(
							(TransferDropTargetListener) new TemplateTransferDropTargetListener(
									getViewer()));
			IToolBarManager tbm = getSite().getActionBars().getToolBarManager();
			showOutlineAction = new Action() {
				public void run() {
					showPage(ID_OUTLINE);
				}
			};
			showOutlineAction.setImageDescriptor(ImageDescriptor
					.createFromFile(AtomBuilderPlugin.class, "icons/outline.gif")); //$NON-NLS-1$
			showOutlineAction.setToolTipText("outline");
			tbm.add(showOutlineAction);
			showOverviewAction = new Action() {
				public void run() {
					showPage(ID_OVERVIEW);
				}
			};
			showOverviewAction.setImageDescriptor(ImageDescriptor
					.createFromFile(AtomBuilderPlugin.class, "icons/overview.gif")); //$NON-NLS-1$
			showOverviewAction
					.setToolTipText("view");
			tbm.add(showOverviewAction);
			showPage(ID_OUTLINE);
		}

		public void createControl(Composite parent) {
			pageBook = new PageBook(parent, SWT.NONE);
			outline = getViewer().createControl(pageBook);
			overview = new Canvas(pageBook, SWT.NONE);
			pageBook.showPage(outline);
			configureOutlineViewer();
			hookOutlineViewer();
			initializeOutlineViewer();
		}

		public void dispose() {
			unhookOutlineViewer();
			if (thumbnail != null) {
				thumbnail.deactivate();
				thumbnail = null;
			}
			super.dispose();
		}

		public Object getAdapter(Class type) {
			if (type == ZoomManager.class)
				return getGraphicalViewer().getProperty(
						ZoomManager.class.toString());
			return null;
		}

		public Control getControl() {
			return pageBook;
		}

		protected void hookOutlineViewer() {
			getSelectionSynchronizer().addViewer(getViewer());
		}

		protected void initializeOutlineViewer() {
			setContents(getDiagram());
		}

		protected void initializeOverview() {
			LightweightSystem lws = new LightweightSystem(overview);
			RootEditPart rep = getGraphicalViewer().getRootEditPart();
			if (rep instanceof ScalableFreeformRootEditPart) {
				ScalableFreeformRootEditPart root = (ScalableFreeformRootEditPart) rep;
				thumbnail = new ScrollableThumbnail((Viewport) root.getFigure());
				thumbnail.setBorder(new MarginBorder(3));
				thumbnail.setSource(root
						.getLayer(LayerConstants.PRINTABLE_LAYERS));
				lws.setContents(thumbnail);
				disposeListener = new DisposeListener() {
					public void widgetDisposed(DisposeEvent e) {
						if (thumbnail != null) {
							thumbnail.deactivate();
							thumbnail = null;
						}
					}
				};
				getEditor().addDisposeListener(disposeListener);
			}
		}

		public void setContents(Object contents) {
			getViewer().setContents(contents);
		}

		protected void showPage(int id) {
			if (id == ID_OUTLINE) {
				showOutlineAction.setChecked(true);
				showOverviewAction.setChecked(false);
				pageBook.showPage(outline);
				if (thumbnail != null)
					thumbnail.setVisible(false);
			} else if (id == ID_OVERVIEW) {
				if (thumbnail == null)
					initializeOverview();
				showOutlineAction.setChecked(false);
				showOverviewAction.setChecked(true);
				pageBook.showPage(overview);
				thumbnail.setVisible(true);
			}
		}

		protected void unhookOutlineViewer() {
			getSelectionSynchronizer().removeViewer(getViewer());
			if (disposeListener != null && getEditor() != null
					&& !getEditor().isDisposed())
				getEditor().removeDisposeListener(disposeListener);
		}
	}
}
